package com.paraz.cst.impl;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;

import com.paraz.cst.CstException;
import com.paraz.cst.CstLooper;

public class RealCstSocketServer<E> {

	private int port;

	private CstLooper<E> cstLooper;

	private ExecutorService executorService;

	public CstLooper<E> getCstLooper() {
		return cstLooper;
	}

	public void setCstLooper(CstLooper<E> cstLooper) {
		this.cstLooper = cstLooper;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public ExecutorService getExecutorService() {
		return executorService;
	}

	public void setExecutorService(ExecutorService executorService) {
		this.executorService = executorService;
	}

	/**
	 * Serve.
	 */
	public void serve() throws CstException {
		try {
			final ServerSocket serverSocket = new ServerSocket(port);
			while (true) {
				// accept() blocks.
				Socket socket;
				socket = serverSocket.accept();
				executorService.execute(new Worker(new RealCstSocket(socket)));

			}
		} catch (IOException e) {
			throw new CstException(e);
		}
	}

	/**
	 * Worker for ExecutorService. Simply adapts to the Looper.
	 * 
	 * @author mparaz
	 * 
	 */
	private class Worker implements Runnable {

		private RealCstSocket realCstSocket;

		private Worker(RealCstSocket realCstSocket) {
			this.realCstSocket = realCstSocket;
		}

		public void run() {
			cstLooper.loop(realCstSocket);
		}

	}
}
